package pl.genzy.converter;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class Converter {

	//attributes
	private BufferedImage image;
	
	private ArrayList<ArrayList<MyInt>> veritical;
	private ArrayList<ArrayList<MyInt>> horizontal;
	private boolean[] solution;
	
	private boolean continousFlag;
	private MyInt currentCounter;
	
	//constructor
	public Converter(BufferedImage image) {
		if(image == null)
			throw new NullPointerException("dev: image must be specified");
		
		this.image = image;
		veritical = null;
		horizontal = null;
		
		continousFlag = false;
	}
	
	//MyInt subclass
	class MyInt { //foo int because Integer++ does not work as it should :/
		public int i;
		
		public MyInt(int init) {
			i = init;
		}
		
		public MyInt increment(int value) {
			i += value;
			return this;
		}
		
		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append(i);
			
			return builder.toString();
		}
	}
	
	//methods
	private ArrayList<ArrayList<MyInt>> initBlackBitCounter(int count) {
		ArrayList<ArrayList<MyInt>> value = new ArrayList<ArrayList<MyInt>>(count);
		
		for(int i = 0; i < count; i++)
			value.add(new ArrayList<MyInt>());
		
		return value;
	}
	
	public ArrayList<ArrayList<MyInt>> getVeriticalNumbers() {
		if(veritical != null)
			return veritical;
		
		veritical = initBlackBitCounter(image.getHeight());
		continousFlag = false;
		currentCounter = null;
		
		for(int i = 0; i < image.getHeight(); i++) {
			continousFlag = false;
			currentCounter = null;
			
			for(int j = 0; j < image.getWidth(); j++) {
				int value = image.getRGB(j, i) == -1 ? 0 : 1;
				
				if(value == 1) {
					if(continousFlag)
					{
						currentCounter.increment(1);
					}
					else
					{
						currentCounter = new MyInt(1);
						veritical.get(i).add(currentCounter);
						
						continousFlag = true;
					}
				}
				else
					continousFlag = false;
			}
		}
		
		return veritical;
	}
	
	public ArrayList<ArrayList<MyInt>> getHorizontalNumbers() {
		if(horizontal != null)
			return horizontal;
		
		horizontal = initBlackBitCounter(image.getWidth());
		continousFlag = false;
		currentCounter = null;
		
		for(int i = 0; i < image.getWidth(); i++) {
			continousFlag = false;
			currentCounter = null;
			
			for(int j = 0; j < image.getHeight(); j++)
			{
				int value = image.getRGB(i, j) == -1 ? 0 : 1;
				
				if(value == 1) {
					if(continousFlag)
					{
						currentCounter.increment(1);
					}
					else
					{
						currentCounter = new MyInt(1);
						horizontal.get(i).add(currentCounter);
						
						continousFlag = true;
					}
				}
				else
					continousFlag = false;
			}
		}
		
		return horizontal;
	}
	
	private Integer horizontalHeight;
	public int getMaxHorizontalHeight() {
		if(horizontalHeight != null)
			return horizontalHeight;
		
		horizontalHeight = new Integer(getHeight(getHorizontalNumbers()));
		
		return horizontalHeight;
	}
	
	private Integer veriticalHeight;
	public int getMaxVeriticalHeight() {
		if(veriticalHeight != null)
			return veriticalHeight;
		
		veriticalHeight = new Integer(getHeight(getVeriticalNumbers()));
		
		return veriticalHeight;
	}
	
	private int getHeight(ArrayList<ArrayList<MyInt>> arg) {
		int size = 0;
		
		for(int i = 0; i < arg.size(); i++)
			if(arg.get(i).size() > size)
				size = arg.get(i).size();
		
		return Math.max(1, size);
	}
	
	public int xy2idx(int x, int y) {
		return x * image.getWidth() + y;
	}
	
	public boolean[] getSolution() {
		if(solution != null)
			return solution;
		
		solution = new boolean[image.getHeight() * image.getWidth()];
		
		for(int row = 0; row < image.getHeight(); row++)
			for(int column = 0; column < image.getWidth(); column++)
				solution[xy2idx(row, column)] = image.getRGB(column, row) == -1 ? false : true;
		
		return solution;
	}
	
	public Dimension getDimension() {
		return new Dimension(image.getWidth(), image.getHeight());
	}
}
